﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GameEngine;
using GameMatchControl.Layout;

namespace GameMatchControl.LayoutEngine
{
    /// <summary>
    /// Abstract class for layout builders
    /// </summary>
    internal abstract class AbstractLayoutBuilder
    {
        private Stack<Area> _areaStack;

        public AbstractLayoutBuilder()
        {
            _areaStack = new Stack<Area>();
        }

        /// <summary>
        /// The API method for building the layout
        /// </summary>
        public GameMatchArea BuildLayout(GameTree root, GameManager gm)
        {
            return TraverseTree(root, gm) as GameMatchArea;
        }

        /// <summary>
        /// internal tree traversing method
        /// </summary>
        private Area TraverseTree(GameTree parent, GameManager gm)
        {
            // process parent node
            Area nodeArea = ProcessNode(parent, gm);

            // if no children nodes - exit
            if (parent.GetChildCount() == 0)
                return nodeArea;

            // signal entering lower level of the treee
            EnteringBranch(parent);

            // process child nodes
            foreach (var childItem in parent.ChildNodes)
            {
                TraverseTree(childItem, gm);
            }

            // signal leaving branch
            LeavingBranch(parent);

            return nodeArea;
        }


        #region Abstract Methods 

        protected abstract void EnteringBranch(GameTree parent);

        protected abstract void LeavingBranch(GameTree parent);

        protected abstract Area ProcessNode(GameTree treeItem, GameManager gm);


        #endregion



        #region Stack Manipulation Routines

        protected void PushArea(Area a) 
        {
            _areaStack.Push(a);
        }

        protected Area PopArea()
        {
            if (_areaStack.Count == 0)
                return null;
            else
                return _areaStack.Pop();
        }

        protected bool IsStackEmpty()
        {
            return _areaStack.Count != 0;
        }

        protected Area StackTop()
        {
            return _areaStack.Peek();
        }

        #endregion
    }
}
